/*
*  Impp - Instant Messenger
*
*  Copyright (C) 2001-2009 Oliver Schneider
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef IMPP_H_
#define IMPP_H_

#include <vector>

#include "interfaces/iProtocol.h"
#include "interfaces/iUserInterface.h"
#include "interfaces/iBuddyList.h"

#include "settings/Settings.h"

#include "Group.h"
#include "Buddy.h"
#include "database/Database.h"
#include "events/StatusEventTypes.h"
#include "events/MessageCallbackEvent.h"
#include "events/TypingNotificationEvent.h"
#include "notification/NotificationSystem.h"
#include "actions/ActionManager.h"
#include "modules/ModuleManager.h"

namespace Impp {

/**
 *  This is the main control class for all important things that
 *  can happen, like Incoming and outgoing Message, all kind of
 *  requests and changes.
 *
 * 	If you want to change something, like the customName of a buddy
 *  or your own avatar etc. you should always call methods from
 *  this class. This is very important, because the class take care
 *  about updating all other components like the database and the
 *  userinterface.
 *
 *  The functions starting with process* normal coudn't be called
 *  from not Protocol classes. They are a kind of callback function
 *  to a response from an request, change, set or connect, disconnect process.
 *
 */
class Impp : public wxEvtHandler
{

private:
	//singleton
	static Impp* instanz;

	wxString profilFolder;
	wxString pixmapsFolder;

	Group* rootGroup;
	Group* notInListGroup;

	Settings* settings;

	ActionManager* actions;
	ModuleManager* modules;

	std::vector<Account*> accounts;

	std::vector<Buddy*> buddies;
	std::vector<Group*> groups;

	Database* db;
	NotificationSystem* notfications;
	PrivacySetting masterVisibility;
	ConnectionState masterConnectionState;


private:
	Impp();
	virtual ~Impp();

public:
	static Impp* exemplar();
    /**
     *  @brief  inits impp
     *  @param  pProfilDir  the directory where user-files should be stored, if this
     * 						is a empty string, Impp uses platform defaults user-directory
     *
     *  determined directories to use, creates the database,
     *  loads Groups and Buddies, creates the buddylist and so on.
     */
	void init(const wxString & pProfilDir);
    /**
     *  @brief  get the group or creates it if it doesn't exist
     *  @param  groupName  the name of the group to get or create
     *  @return pointer to requested Group, can be stored
     *
     *  returns the Group with the given name from the Grouplist or
     * 	if the group doesn't exist, creates a group with the name and returns it.
     *
     *  Attention: if you know the id of the group you want to get, use
     *  getGroup(const size_t id) instead.
     *
     */
	Group* getOrCreateGroup(const wxString & groupName);
    /**
     *  @brief  gets the buddy or creates it if it doesn't exist
     *  @param  accountId the id of the account the buddy should belong to
     *  @param  screenName the screenName of the buddy to get or create
     *  @param  subGroup if buddy exists: ignored, else this will be the created buddies group
     *  @param  customName if buddy exists: ignored, else this will be the created buddies customName
     * 	@return pointer to requested Buddy, can be stored
     *
     *  returns the buddy with the given screenName from the list of buddies or
     * 	if the buddy doesn't exist, creates a buddy with the screenName, subGroup, customName and flags: BUDDY_FLAG_NOT_INLIST|BUDDY_FLAG_NOAUTHORISATION and returns it.
     *  if the buddy exists already, all additional parameters will be ignored.
     */
	Buddy* getOrCreateBuddy(const db_id & accountId, const wxString & screenName, Group* subGroup,const wxString & customName = wxEmptyString);
    /**
     *  @brief  gets the buddy with the given screenName
     *  @param  accountId the id of the account the buddy belongs to
     *  @param  screenName the screenName of the buddy to get
     *  @return pointer to requested Buddy, can be stored or NULL if the buddy doen't exist
     *
     *  returns the buddy with the given screenName.
     *  if the buddy doesn't exist, the function returns NULL
     */
	Buddy* getBuddy(const db_id & accountId, const wxString & screenName);
    /**
     *  @brief  gets the group with the given id
     *  @param  id the id of the group to get
     *  @return pointer to requested Group, can be stored or NULL if the group doen't exist
     *
     *  returns the group with the given id.
     *  if the group doesn't exist, the function returns NULL
     */
	Group* getGroup(const size_t id);
    /**
     *  @brief  gets a list with all buddies
     *  @return a vector of all buddies currently loaded
     *
     *  The list will be a copy of the real vector with all buddies.
     *  The list contains buddies that are not in the buddylist!
     *
     *  Normal you shouldn't store this list, just use it temporary,
     *  because the real list of buddies can be changed during time.
     *  the list doen't contain your self buddy object.
     */
	std::vector<Buddy*> getAllBuddies();
    /**
     *  @brief  gets a list with all buddies with the accountId
     *
     *  @param  accountId just Buddies with this acctionId are getted
     *  @param  out an empty vector that will be filled with the buddies
     *
     *  The list will be a copy of the real vector with all buddies.
     *  The list contains buddies that are not in the buddylist!
     *
     *  Normal you shouldn't store this list, just use it temporary,
     *  because the real list of buddies can be changed during time.
     *  the list doen't contain your self buddy object.
     */
	void getBuddiesFromAccount(const db_id & accountId, std::vector<Buddy*> & out);
    /**
     *  @brief  gets a list with all groups
     *  @return a vector of all groups currently loaded
     *
     *  The list will be a copy of the real vector with all groups.
     *
     *  Normal you shouldn't store this list, just use it temporary,
     *  because the real list of groups can be changed during time.
     */
	std::vector<Group*> getAllGroups();
    /**
     *  @brief  gets your buddy-object
     *  @return a pointer to your buddy object, can be stored
     *
	 *  Gets your buddy-object, that contains your screenName and so on.
     */
	Buddy* getSelf(const db_id & accountId);
    /**
     *  @brief  gets the RootGroup
     *  @param  accountId the self of this account
     *  @return a pointer to the rootGroup, can be stored
     *
	 *  Gets the RootGroup. THe RootGroup it the Group witch contains all SubGroups.
	 *  It can also contain buddies
     */
	Group* getRootGroup();
    /**
     *  @brief  gets the NotInListGroup
     *  @return a pointer to the NotInListGroup, can be stored
     *
	 *  Gets the NotInListGroup. The NotInListGroup contains all buddies that aren't in your
	 *  buddylist, but are needed because they send you a addToBuddylist request, a message
	 *  or you want to add them.
     */
	Group* getNotInListGroup();
    /**
     *  @brief  processes a buddy status change notification from a protocol
     *  @param  b the buddy whose status has changed
     *  @param  s (new) Status of the buddy
     *	@param  statusMsg the (new) status Message
     * 	@param  statusConnectionType the StatusConnectionType can be:
     * 			STATUS_EVENT_SELF_CONNECTION: The buddy changes his status from unknown to his real status, because
     * 									  	  the protocol has connected and the real status can be detected
     * 			STATUS_EVENT_SELF_DISCONNECTION: The protocol is connected and this is a normal status change
     *          STATUS_EVENT_SELF_CONNECTED: The protocol is disconnected and so the buddy status changes to UNKNOWN
     *
     *  This function should be only called from a protocol!
     *  The function checks if the status or statusMsg is really new
     *  and then updates the buddy an creates an StatusEvent
     */
	void processBuddyStatusChanged(Buddy* b,const Status & s, const wxString & statusMsg, const StatusConnectionType & statusConnectionType = STATUS_EVENT_SELF_CONNECTED);
    /**
     *  @brief  processes a incoming message from an protocol
     *  @param  sender the sender of the message
     *  @param  time the time of the message
     *	@param  msg the message itself as string
     *	@param  bitmask of additional flags, which describes the message: MESSAGE_EVENT_NORMAL_MESSAGE,
     * 																	 MESSAG_EVENT_OFFLINE_MESSAGE,
     * 																	 MESSAGE_EVENT_URL_MESSAGE
     *
     *  This function should be only called from a protocol!
     *  checks the message and creates a MessageEvent
     */
	void processMessageIn(Buddy* sender,const wxDateTime & time, wxString & msg, int/*<MessageEventType>*/ messageEventType);
    /**
     *  @brief  processes a message send callback
     *  @param  id the ActionId of the corresponding sendMessage
     *  @param  buddy the buddy the message was addressed to
     *	@param  state one of the success states or MESSAGE_STATE_FAILED
     *  @param  error id state = MESSAGE_STATE_FAILED then an error state else MESSAGE_ERROR_NO
     *  @param  A Message String that describes the error (if any) and if error = MESSAGE_ERROR_OTHER
     *
     *  This function should be only called from a protocol!
     *  checks the messageCallback and creates a MessageCallbackEvent
     */
	void processMessageSendCallback(const ActionId & id, Buddy* buddy,MessageState state, MessageError error = MESSAGE_ERROR_NO,const wxString & errorString = wxEmptyString);
    /**
     *  @brief  processes a avatar received
     *  @param  id the ActionId of the corresponding requestAvatar
     *  @param  buddy the buddy whose avatar was requested
     *	@param  file just the filename of the avatar file (e.g. 1233434.jpg) without path and
     * 			the file has to be in the avatar directory
     *
     *  This function should be only called from a protocol!
     *  registers the avatar for the buddy and creates a AvatarReceivedEvent to inform the
     *  BuddyList and opened ChatWindows
     */
	void processBuddyAvatarReceived(const ActionId & id, Buddy* buddy ,const wxString & file);
    /**
     *  @brief  processes a avata Received Error
     *  @param  id the ActionId of the corresponding requestAvatar
     *
     *  This function should be only calle from a protocol!
     *  The function should be called if an requestet Avatar coudn't getted.
     */
	void processAvararRequestError(const ActionId & id);
    /**
     *  @brief  processes a incoming typing notification
     *  @param  buddy the sender of the typing notification
     *  @param  state the state of typing (begin, end, stopped)
     *
     *  This function should be only called from a protocol!
     *  Creates a TypingNotificationEvent to inform BuddyList, Popups etc...
     */
	void processTypingNotification(Buddy* buddy, TypingState state);
    /**
     *  @brief  processes a incoming authorization
     *  @param  buddy the buddy who requested the authorisation
     *  @param  reason the reason the buddy gave
     *
     *  This function should be only called from a protocol!
     */
	void processAuthorisationRequest(Buddy* buddy ,const wxString & authReason);
    /**
     *  @brief  processes a incoming FileTransfare
     *  @param  buddy the buddy who sends the file
     *  @param  filename the filename or directory name of the file or dir that is requested to send
     *  @param  fileCount the number or files
     *  @param  fileSize the total size of all files
     *
     *  @return a ActionId to identify this request later
     *
     *  If the fileCount is 1 then the filename should be the name of this 1 file,
     *  else it should be the name of the directory, which contains all other files or empty.
     *
     *  The function creates a incomingFileEvent and notifies the ChatWindow, Popupsystem and the
     *  shows the User a Dialog, so he can accept or cancel the transfer.
     *  This function should be only called from a protocol!
     */
	ActionId processIncomingFileTransfare(Buddy* buddy, const wxString & filename, size_t fileCount, size_t fileSize);
    /**
     *  @brief  processes the user-reaction for an incoming FileTransfare
     *  @param  buddy the buddy who sends the file
     *  @param  filename the filename or directory name of the file or dir that is requested to send
     *  @param  fileCount the number or files
     *  @param  fileSize the total size of all files
     *
     *  @return a ActionId to identify this request later
     *
     *  if the fileCount is 1 then the filename should be the name of this 1 file,
     *  else it should be the name of the directory, which contains all other files or empty.
     *
     *  The function creates a incomingFileEvent and notifies the ChatWindow, Popupsystem and the
     *  shows the User a Dialog, so he can accept or cancel the transfer.
     *  This function should be only called from a protocol!
     */
	void processIncomingFileAccept(const ActionId & id, bool accept);
    /**
     *  @brief  processes a change of the customName of a buddy
     *  @param  buddy the buddy whose name has changed or self if your name changed
     *  @param  newCustomName the new customName of the Buddy
     *
     *  Updates the customName of the buddy object, the corresponding database entry
     *  and informs the buddylist and other gui elements to represented the change
     */
	void processCustomNameChange(Buddy* buddy,const wxString & newCustomName);
    /**
     *  @brief  processes a change of your own screenName
     *  @param  newScreenName the new ScreenName of yourself
     *
     *  Updates the newScreenName of the buddy object, the corresponding database entry
     *  and informs the buddylist and other gui elements to represented the change
     *
     * 	This method should only be called if you change your account data in the settings
     */
	void processOwnScreenNameChange(const db_id & accountId, const wxString & newScreenName);
    /**
     *  @brief  processes a change of a buddy's subGroup
     *  @param  buddy the buddy, whose group has changed
     *  @param  newGroup the new Group of the buddy
     *
     *  Removes the buddy from his old group, adds it to the new
     *  group, informs the buddylist about the group change,
     *  updates the changes in the database.
     */
	void processBuddyMove(Buddy* buddy, Group* newGroup);
    /**
     *  @brief  processes a change of UserInfo
     *  @param  buddy the buddy, whose user-info has changed
     *
     *  Updates all opened UserInfo Dialogs, so that they can represent the changes
     */
	void processFullUserInfoChange(Buddy* buddy);
    /**
     *  @brief  processes that your own Status has changed
     *  @param  id the ActionId the function setStatus(const Status & status,const wxString & statusMsg = wxEmptyString) returned
     *  @param  status the status that was setted
     *
     *  This function should be only called from a protocol
     *  (or inside from Impp)!
     *  Updates the status of yourself and if the new status is OFFLINE all
     *  ONLINE buddies will be set to UNKNOWN and if the new status is ONLINE all
     *  UNKNOWN buddies will be set to OFFLINE.
     */
	void processOwnStatusChanged(const db_id & accountId, const ActionId & id, const Status & status);
    /**
     *  @brief  processes that a protocol has connected
     *  @param  id the ActionId the function connect(const Status & status,const wxString & statusMsg, const PrivacySetting & visibility) returned,
     *  @param  status the status that was set
     *
     *  This function should be only called from a protocol!
     */
	void processConnectionEstablished(const db_id & accountId, const ActionId & id, const Status & status);
    /**
     *  @brief  processes that a protocol has disconnected
     *  @param  id the ActionId disconnect() returned or -1 if connectionLost was not requested
     *  @param  reason the reason the connection was lost
     *
     *  This function should be only called from a protocol!
     */
	void processConnectionLost(const db_id & accountId, const ActionId & id, const wxString & reason);
    /**
     *  @brief  processes that the user has read all unread Messages for this buddy
     *  @param  buddy all unreadMessage for this Buddy will be marked as read
     *
     *  Processes that the user has read all unread Messages for this buddy
     */
	void processUnreadMessageRead(Buddy* buddy);
	/**
	 * @brief processes that a buddy was added to a Privacylist
	 * @param buddy the buddy, who was added
	 * @param privacyList the list the buddy was added to
	 *
	 * Processes that a buddy was added to a Privacylist.
	 * Should only be called from a Protocol if it detected a change or from Impp itself.
	 */
	void processAddedToPrivacyList(Buddy* buddy, const BuddyPrivacyList & privacyList);
	/**
	 * @brief processes that a buddy was removed from a Privacylist
	 * @param buddy the buddy, who was removed
	 * @param privacyList the list the buddy was removed from
	 *
	 * Processes that a buddy was removed from Privacylist.
	 * Should only be called from a Protocol if it detected a change or from Impp itself.
	 */
	void processRemoveFromPrivacyList(Buddy* buddy, const BuddyPrivacyList & privacyList);

	/**
     * @param buddy the buddy whose authorisation you lost
     *
     * Processes that a buddy has no authorisation anymore.
     * Should only be called from a Protocol if it detected a change or from Impp itself.
     */
	void processBuddyNoAuthorisationAnymore(Buddy* buddy);

	/**
	 * @param buddy the buddy whose authorisation you got
	 *
	 * Processes that a buddy has now authorisation.
	 * Should only be called from a Protocol if it detected a change or from Impp itself.
	 */
	void processAuthorisationGranded(Buddy* buddy);

	void processSettingChangedInt(const DBModule & module, const wxString & settingName, int newValue);
	void processSettingChangedString(const DBModule & module, const wxString & settingName, const wxString & newValue);
	void processCommandAction(const wxString & moduleName, const wxString & action, bool isChecked = true,  Buddy* buddy = NULL, Group* group = NULL);

	/**
     *  @brief  sends a message to the buddy
     *  @param  buddy the receiver of the message
     *  @param  msg the message to send
     *  @returns ActionId a id to identify the messageCallBack
     *
     *  Sends the Message, if you are connected and the message can be send.
     *  Always creates a MessageCallBackEvent that holds infos if the message
     *  was sent or not and if the server accepted the message or not.
     */
	ActionId sendMessage(Buddy* buddy, const wxString & msg);
    /**
     *  @brief  sends a typing notification to the buddy
     *  @param  buddy the receiver of the typing notification
     *  @param  state	the state of typing:
     * 					TYPING_STARTED: you have started to type
     * 					TYPING_FINISHED: you have finished typing
     * 					TYPING_TEXT_TYPED: you have typed a text, but not send it
     *
     *  Sends the TypingNotification if you are connected and the buddy is online.
     *  There is currently no callback, if the notification was sent or not
     */
	void sendTypingNotification(Buddy* buddy, TypingState state);
    /**
     *  @brief request the avatar of a buddy
     *  @param  buddy the buddy, whose avatar should be requested
     *  @returns ActionId a id to identify the AvatarRequest
     *
     *  Request the avatar of the Buddy, if no request for this buddy is currently done
     *  and you are connected.
     */
	ActionId requestAvatar(Buddy* buddy);
    /**
     *  @brief request the status message of the Buddy
     *  @param  buddy the buddy, whose status message should be requested
     *
     *  Request the status message of the Buddy, if you are connected.
     */
	void requestStatusMessage(Buddy* buddy);
    /**
     *  @brief request the short userinfo of the Buddy
     *  @param  buddy the buddy, whose userinfo should be requested
     *
     *  Request the short userinfo of the Buddy, if you are connected.
     *  A short userinfo typically contains: nickname, first name, last name
     */
	void requestShortUserInfo(Buddy* buddy);
    /**
     *  @brief request the full userinfo of the Buddy
     *  @param  buddy the buddy, whose userinfo should be requested
     *
     *  Request the full userinfo of the Buddy, if you are connected.
     *  A full userinfo typically contains additional infos like: birthday,
     *  address and so on...
     */
	void requestFullUserInfo(Buddy* buddy);
    /**
     *  @brief checks the status of the buddy
     *  @param  buddy the buddy, whose status should be checked
     *
     *  this statuscheck could be used for buddies that aren't allowed
     *  you to add them to your list and so their status isn't automatically
     *  updated or for buddies that are displayed as offline and you want to
     *  check (with the help of protocol exploits) if the buddy is really offline
     *  or if he is invisible (known as invisible check).
     */
	void checkBuddyStatus(Buddy* buddy);
    /**
     *  @brief change the customName of a Buddy
     *  @param  buddy the buddy, whose customName should be changed
     *  @param  newCustomName the new customName to set
     *
	 *  Changed the customName of the buddy. This method includes the
	 *  call to the protocol to change the name on the server.
	 *  This method calls processCustomNameChange(Buddy* buddy,const wxString & newCustomName)
	 *  to inform and update the rest of the system about the change.
     */
	void changeBuddyCustomName(Buddy* buddy, const wxString & newCustomName);
    /**
     *  @brief  changed the subGroup of a buddy
     *  @param  buddy the buddy, whose group should change
     *  @param  newGroup the new subGroup of the buddy
     *
     *  Changed the subGroup of a buddy. This method includes the
	 *  call to the protocol to change the group on the server.
	 *  This method calls processBuddyMove(Buddy* buddy, Group* newGroup)
	 *  to inform and update the rest of the system about the change.
     */
	void changeBuddyGroup(Buddy* buddy, Group* newGroup);
    /**
     *  @brief  adds the buddy to the privacyList
     *  @param  buddy the buddy, who should be set to the list
     *  @param  privacyList 	the list the buddy should be added to.
     * 							one of: BUDDY_PRIVACY_INVISIBLELIST,
     * 									BUDDY_PRIVACY_VISISBLELIST,
     * 									BUDDY_PRIVACY_IGNORED
     *
	 * Adds the buddy to the privacyList. If the list is BUDDY_PRIVACY_INVISIBLELIST,
	 * then this method removes the buddy from the BUDDY_PRIVACY_VISISBLELIST and if
	 * the list is BUDDY_PRIVACY_VISISBLELIST, the buddy is removed from the BUDDY_PRIVACY_INVISIBLELIST,
	 * because the buddy can't be on both lists. It wouldn't make sense.
	 * This method calls porzessListSettingsChange(...)
	 * to inform and update the rest of the system about the changes.
     */
	void changeAddToPrivacyList(Buddy* buddy, const BuddyPrivacyList & privacyList);
    /**
     *  @brief  removes the buddy from the privacyList
     *  @param  buddy the buddy, who should be removed from  the list
     *  @param  privacyList 	the list the buddy should be removed from.
     * 							one of: BUDDY_PRIVACY_INVISIBLELIST,
     * 									BUDDY_PRIVACY_VISISBLELIST,
     * 									BUDDY_PRIVACY_IGNORED
     *
	 * Removes the buddy to the privacyList.
	 * This method calls porzessListSettingsChange(...)
	 * to inform and update the rest of the system about the changes.
     */
	void changeRemoveFromPrivacyList(Buddy* buddy, const BuddyPrivacyList & privacyList);

	/**
	 * @brief Changes the priority of the buddy to low, normal or high
	 *
	 * @param buddy the buddy, whose priority should be changed
	 * @param flags one of BUDDY_PRIORITY_NORMAL,
	 * 					   BUDDY_PRIORITY_LOW,
	 *					   BUDDY_PRIORITY_HIGH
	 * Changes the priority of the buddy to low, normal or high.
	 */
	void changeBuddyPriority(Buddy* buddy,const BuddyPriority & flag);
	/**
     *  @brief  changes your avatar to the given file
     *  @param 	accountId 	account from wich avatar should be changed
     *  @param  file	the full filepath to the image, that should be used
     *  				as new avatar. The file can be any size and one of
     * 					the imageformats that can be handled.
     *
     * Changes your avatar to the given file. Resizes the file to the maximum avatar size for
     * the protocol and copies the resized file into the avatar directory and call the protocol
     * to upload the file. Then calls processAvatarReceived(const ActionId & id, Buddy* b,const wxString & file)
     * to inform the Rest of the System about the changed avatar.
     */
	void changeOwnAvatar(const db_id & accountId, const wxString & file);
    /**
     *  @brief  connects to the server
     *  @param  accountId the accountId of the account that should be connected
     *  @param  status	the status to set as online status
     *  @param  statusMsg the statusMsg to set
     *  @param  visibility the visibility to set
     *  @return ActionId to follow the connection-process or -1 if you aren't disconnected.
     *
     *  Connects to the server, if you aren't already connected or are already connecting.
     *  Returns an ActionId to follow the connection-process. If connection coudn't established,
     *  this function returns -1. However, if the function returns an valid ActionId, this doesn't
     *  mean connection was successful, this only means that impp is trying to connect!
     */
	ActionId connect(const db_id & accountId);
    /**
     *  @brief  disconnects a protocol
     *
     *  Disconnects from the server.
     */
	void disconnect(const db_id & accountId);
    /**
     *  @brief  get the ConnectionState
     * 	@return ProtocolState the ConnectionState, one of:
     * 			PROTOCOL_STATE_DISCONNECTED: You are disconnected
     * 			PROTOCOL_STATE_CONNECTING: you are trying to connect
     * 			PROTOCOL_STATE_CONNECTED: you are connected
     *
     *  Returns the ProtocolState
     */
	ConnectionState getConnectionState(const db_id & accountId);
    /**
     *  @brief  sets your online status and status message
     *  @param  status	the status to set as online status
     *  @param  statusMsg the statusMsg to set
     *  @return ActionId to follow the setStatusprocess or connection-process or -1 if disconnecting
     *
     *  If you aren't yet connected and the status to set is not OFFLINE,
     *  connects to the server and returns the ActionID of the connectAction.
     *  If you are connected and the new status to set is OFFLINE,
     *  then disconnect from the server and -1 is returned.
     *  If you are connected and the new status isn't OFFLINE, the new status and
     *  statusMsg will be set.
     */
	ActionId setStatus(const db_id & accountId, const Status & status,const wxString & statusMsg = wxEmptyString);


	ActionId setStatusAndChageState(const db_id & accountId, const Status & status,const wxString & statusMsg, const PrivacySetting & privacy);

    /**
     *  @brief  returns a Buddy with unread Message or NULL
     *  @return Buddy with unread Messages or NULL
     *
     *  returns a Buddy with unread Message or NULL if there is no
     *  Buddy with unread messages
     */
	Buddy* getNextBuddyWithUnreadMsgs();


	void changeAccountInfo(const db_id & accountId,const wxString & newScreenName,const  wxString & newPassword);


	PrivacySetting getPrivacySettings(const db_id & accountId);
	void setPrivacySettings(const db_id & accountId, const PrivacySetting & visibility);

	PrivacySetting getMasterPrivacy();
	Status getMasterStatus();

	std::vector<Account*> getAccounts();
	void getActiveAccounts(std::vector<Account*> & out);
	Account* createAccount(const wxString & classname,const wxString & screenName,const wxString & password);
	void deleteAccount(const db_id & id);

	Settings* getSettings();
	Database* getDatabase();
	ActionManager* getActionManager();
	ModuleManager* getModuleManager();

	iProtocol* getProtocolIfActive(const db_id & accountId);

	void close();

	wxString getProfilDir();
	wxString getAvatarDir();
	wxString getPixmapsDir();

	size_t getActiveAccountCount();
	Account* getAccount(const db_id & accountId);

private:
	void addGroupToGroupsAndBuddylist(Group* group);
	void addBuddyToGroupsAndBuddylist(Buddy* b, Group* subGroup);

private:
	DECLARE_EVENT_TABLE()
};

}

#endif /*IMPP_H_*/
